/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */
package com.yami.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.yami.shop.bean.app.dto.MyOrderDto;
import com.yami.shop.bean.app.dto.MyOrderItemDto;
import com.yami.shop.bean.app.dto.OrderCountData;
import com.yami.shop.bean.app.dto.ShopCartOrderMergerDto;
import com.yami.shop.bean.bo.PlatformCommissionOrderItemBO;
import com.yami.shop.bean.enums.*;
import com.yami.shop.bean.event.*;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.param.OrderParam;
import com.yami.shop.bean.param.PayGoodsParam;
import com.yami.shop.bean.vo.OrderAmountVO;
import com.yami.shop.bean.vo.UnDeliveryOrderExcelVO;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.enums.PayType;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.util.Arith;
import com.yami.shop.common.util.CharUtil;
import com.yami.shop.common.util.PageAdapter;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.dao.*;
import com.yami.shop.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lgh on 2018/09/15.
 */
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Value("${yami.expose.operation.auth:}")
    private Boolean permission;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private DeliveryService deliveryService;
    @Autowired
    private NotifyTemplateService notifyTemplateService;
    @Autowired
    private StationService stationService;
    @Autowired
    private OrderItemService orderItemService;
    @Autowired
    private OrderSettlementService orderSettlementService;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    @Autowired
    private OrderLangMapper orderlangMapper;
    @Autowired
    private OrderRefundMapper orderRefundMapper;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private OrderVirtualInfoService orderVirtualInfoService;
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private SkuStockLockService skuStockLockService;
    @Autowired
    private PayInfoMapper payInfoMapper;
    @Autowired
    private ShopWalletService shopWalletService;
    @Autowired
    private ShopWalletMapper shopWalletMapper;
    @Autowired
    private ShopWalletLogService shopWalletLogService;

    @Override
    public Order getOrderByOrderNumber(String orderNumber) {
        return orderMapper.getOrderByOrderNumber(orderNumber);
    }

    @Override
    public Order getOrderByOrderNumberAndUserId(String orderNumber, String userId, boolean valid) {
        Order order = orderMapper.getOrderByOrderNumberAndUserId(orderNumber, userId);
        if (valid && Objects.isNull(order)) {
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }
        return order;
    }

    @Override
    public Order getOrderByOrderNumberAndShopId(String orderNumber, Long shopId, boolean valid) {
        Order order = orderMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNumber, orderNumber).eq(Order::getShopId, shopId));
        if (valid && order == null) {
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }
        return order;
    }


    @Override
    @CacheEvict(cacheNames = "ConfirmOrderCache", key = "#userId")
    public void removeConfirmOrderCache(String userId) {
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Order> submit(ShopCartOrderMergerDto mergerOrder) {
        String userId = mergerOrder.getUserId();
        // 扣减商品库存，本次下单使用的优惠券、积分
        eventPublisher.publishEvent(new TryLockStockEvent(mergerOrder, userId));
        List<Order> orderList = new ArrayList<>();
        // 提交订单
        eventPublisher.publishEvent(new SubmitOrderEvent(mergerOrder, orderList));
        List<OrderItem> orderItems = orderList.stream()
                .flatMap(order -> order.getOrderItems()
                        .stream())
                .collect(Collectors.toList());
        //calculatePlatformCommission(orderList, orderItems);
        // 插入订单
        saveBatch(orderList);
        // 保存订单语言表
        orderlangMapper.insertBatchOrderLang(orderList);
        // 插入订单项，返回主键
        orderItemService.insertBatchOrderItem(orderItems);
        // 只有普通商品才需要处理赠品
        if(Objects.equals(mergerOrder.getOrderType(),OrderType.ORDINARY)){
            // 添加赠品
            eventPublisher.publishEvent(new SubmitOrderGiveawayEvent(orderList, orderItems));
        }
//        //计算积分情况
//        if (mergerOrder.getIsScorePay() != null && mergerOrder.getIsScorePay() == 1) {
//            eventPublisher.publishEvent(new SubmitScoreOrderEvent(mergerOrder, orderList));
//        }
//        List<String> orderNumbers = new ArrayList<>();
//        orderList.forEach(order -> orderNumbers.add(order.getOrderNumber()));
//        // 发送消息，如果三十分钟后没有支付，则取消订单
//        SendStatus sendStatus = orderCancelTemplate.syncSend(RocketMqConstant.ORDER_CANCEL_TOPIC, new GenericMessage<>(orderNumbers), RocketMqConstant.TIMEOUT, RocketMqConstant.CANCEL_ORDER_DELAY_LEVEL).getSendStatus();
//        if (!Objects.equals(sendStatus, SendStatus.SEND_OK)) {
//            // 消息发不出去就抛异常，发的出去无所谓
//            throw new YamiShopBindException(ResponseEnum.EXCEPTION);
//        }
        return orderList;
    }

    /**
     * 计算分摊金额
     */
    private void calculatePlatformCommission(List<Order> orders, List<OrderItem> orderItems) {
        boolean scoreOrder = Objects.equals(orders.get(0).getOrderType(), OrderType.SCORE.value());
        List<PlatformCommissionOrderItemBO> platformCommissionOrderItems = new ArrayList<>();
        for (OrderItem orderItem : orderItems) {
            PlatformCommissionOrderItemBO platformCommissionOrderItemBO = new PlatformCommissionOrderItemBO();
            platformCommissionOrderItemBO.setShopId(orderItem.getShopId());
            platformCommissionOrderItemBO.setCategoryId(orderItem.getCategoryId());
            platformCommissionOrderItemBO.setSkuId(orderItem.getSkuId());
            platformCommissionOrderItems.add(platformCommissionOrderItemBO);
        }
        // 获取整个平台的佣金比例
        List<Category> categoryRates = categoryService.listRate();
        List<PlatformCommissionOrderItemBO> data = categoryService.calculatePlatformCommission(platformCommissionOrderItems, categoryRates);
        for (OrderItem orderItem : orderItems) {
            for (PlatformCommissionOrderItemBO platformCommissionOrderItemBO : data) {
                double platformCommission = 0.0;
                // 积分订单属于平台的订单不需要计算平台佣金
                if (scoreOrder) {
                    orderItem.setPlatformCommission(platformCommission);
                    continue;
                }
                // 通过商品确定订单项
                if (Objects.equals(orderItem.getSkuId(), platformCommissionOrderItemBO.getSkuId())) {
                    // 分摊比例
                    orderItem.setRate(platformCommissionOrderItemBO.getRate());
                    // 平台佣金 = （实付金额 + 平台优惠金额） * 比例 / 100
                    platformCommission = Arith.roundByBanker(Arith.div(Arith.mul(Arith.add(orderItem.getActualTotal(), orderItem.getPlatformShareReduce()),
                            platformCommissionOrderItemBO.getRate()), 100), 2);
                    orderItem.setPlatformCommission(platformCommission);
                }
            }
        }
        Map<String, List<OrderItem>> orderNumberMap = orderItems.stream().collect(Collectors.groupingBy(OrderItem::getOrderNumber));
        for (Order order : orders) {
            double totalPlatformCommission = 0.0;
            List<OrderItem> orderItemList = orderNumberMap.get(order.getOrderNumber());
            for (OrderItem orderItem : orderItemList) {
                totalPlatformCommission = Arith.add(totalPlatformCommission, orderItem.getPlatformCommission());
            }
            order.setPlatformCommission(totalPlatformCommission);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delivery(Order order) {
        orderMapper.updateById(order);
        // 消息推送-发货提醒
        Delivery delivery = deliveryService.getById(order.getDvyId());
        String dvyName = "";
        if (delivery.getDvyName() != null) {
            dvyName = delivery.getDvyName();
        }
        notifyTemplateService.sendNotifyOfDelivery(order, dvyName, SendType.DELIVERY);
    }


    @Override
    public List<Order> listUnRefundOrderAndOrderItems(Integer orderStatus, DateTime lessThanUpdateTime) {
        return orderMapper.listUnRefundOrderAndOrderItems(orderStatus, lessThanUpdateTime);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrders(List<Order> orders) {
        if (CollectionUtil.isEmpty(orders)) {
            return;
        }
        orderMapper.cancelOrders(orders);
        Set<Long> orderSkuIds = new HashSet<>();
        List<OrderItem> allOrderItems = new ArrayList<>();
        for (Order order : orders) {
            List<OrderItem> orderItems = order.getOrderItems();
            allOrderItems.addAll(orderItems);
            orderSkuIds.addAll(orderItems.stream().map(OrderItem::getSkuId).collect(Collectors.toList()));
            eventPublisher.publishEvent(new CancelOrderEvent(order));
        }
        // 如果是秒杀订单也不必还原库存
        if (CollectionUtil.isEmpty(allOrderItems) || OrderType.SECKILL.value().equals(orders.get(0).getOrderType())) {
            return;
        }
        // 解锁库存
        skuStockLockService.unlockStock(orders);

        // 查询出微信支付并且为二维码支付的，失效掉对应支付二维码
        invalidCode(orders);

    }

    private void invalidCode(List<Order> orders) {
        Set<String> userIds = new HashSet<>();
        Set<String> orderNumbers = new HashSet<>();
        for (Order order : orders) {
            if (Objects.isNull(order.getPayType())) {
                continue;
            }
            // 如果是支付宝支付，或者微信 二维码支付直接使二维码失效
            if (Objects.equals(order.getPayType(), PayType.ALIPAY.value()) ||
                    Objects.equals(order.getPayType(), PayType.WECHATPAY_SWEEP_CODE.value())) {
                userIds.add(order.getUserId());
                orderNumbers.add(order.getOrderNumber());
            }
        }
        if (CollectionUtils.isEmpty(userIds)) {
            return;
        }
        // 如果有重复的payNo，不用失效掉二维码。
        List<PayInfo> payInfoList = payInfoMapper.listByUserIdList(userIds, DateUtil.offsetMinute(new Date(), -35));
        Iterator<PayInfo> iterator = payInfoList.iterator();
        while (iterator.hasNext()) {
            PayInfo payInfo = iterator.next();
            String[] orderNumberList = payInfo.getOrderNumbers().split(",");
            for (String orderNumber : orderNumberList) {
                if (!orderNumbers.contains(orderNumber)) {
                    iterator.remove();
                }
            }
        }
        if (CollectionUtils.isEmpty(payInfoList)) {
            return;
        }
        eventPublisher.publishEvent(new PayManagerEvent(payInfoList));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void receiptOrder(List<Order> orders) {
        orderMapper.receiptOrder(orders);
        for (Order order : orders) {
            eventPublisher.publishEvent(new ReceiptOrderEvent(order));
            // 消息推送-用户已确认收货
            notifyTemplateService.sendNotifyByUserRefundDelivery(order, SendType.RECEIPT_ORDER);
        }

    }

    @Override
    public IPage<Order> pageOrdersDetailByOrderParam(Page<Order> page, OrderParam orderParam) {
        Date date = new Date();
        List<Order> orders = orderMapper.listOrdersDetailByOrderParam(new PageAdapter(page), orderParam);
        for (Order order : orders) {
            if (StrUtil.isNotBlank(order.getReceiverName()) && CharUtil.length(order.getReceiverName()) > 8) {
                order.setReceiverName(order.getReceiverName().substring(0, Math.min(8, order.getReceiverName().length() - 1)) + "...");
            }
            if (BooleanUtil.isFalse(permission)) {
                order.setReceiverMobile(order.getReceiverMobile() != null ? PhoneUtil.hideBetween(order.getReceiverMobile()).toString() : null);
                if (Objects.nonNull(order.getUserAddrOrder())) {
                    order.getUserAddrOrder().setMobile(order.getUserAddrOrder().getMobile() != null ? PhoneUtil.hideBetween(order.getUserAddrOrder().getMobile()).toString() : order.getUserAddrOrder().getMobile());
                }
            }
            if (Objects.equals(order.getOrderMold(), 1) && Objects.nonNull(order.getWriteOffEnd()) && DateUtil.compare(order.getWriteOffEnd(), date) < 0) {
                order.setWriteOffCodes(new ArrayList<>());
            }

            // 预售商品处理
            if (Objects.nonNull(order.getPreSaleTime())) {
                for (OrderItem orderItem : order.getOrderItems()) {
                    Product product = null;
                    boolean oneOrderItem = order.getOrderItems().size() == 1;
                    if (!oneOrderItem) {
                        product = productMapper.selectById(orderItem.getProdId());
                    }

                    if (oneOrderItem || (Objects.nonNull(product) && Objects.equals(product.getPreSellStatus(), 1))) {
                        orderItem.setPreSaleTime(order.getPreSaleTime());
                        break;
                    }
                }
            }

            // 处理套餐的预售订单

            // 处理赠品列表
            Map<Long, List<OrderItem>> giveawayMap = order.getOrderItems().stream().filter(orderItem -> Objects.nonNull(orderItem.getGiveawayOrderItemId())).collect(Collectors.groupingBy(OrderItem::getGiveawayOrderItemId));
            if (MapUtil.isNotEmpty(giveawayMap)) {
                Iterator<OrderItem> iterator = order.getOrderItems().iterator();
                while (iterator.hasNext()) {
                    OrderItem orderItem = iterator.next();
                    if (Objects.nonNull(orderItem.getGiveawayOrderItemId())) {
                        iterator.remove();
                    }
                    orderItem.setGiveawayList(giveawayMap.get(orderItem.getOrderItemId()));
                }
            }
        }
        page.setRecords(orders);
        page.setTotal(orderMapper.countOrderDetail(orderParam));
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteOrders(List<Order> orders) {
        orderMapper.deleteOrders(orders);
    }

    @Override
    public OrderCountData getOrderCount(String userId) {
        // 获取普通订单数据
        OrderCountData countData = orderMapper.getOrderCount(userId);
        // 获取退款订单数据
        countData.setRefund(orderRefundMapper.getRefundCount(userId));
        return countData;
    }

    @Override
    public double sumTotalDistributionAmountByOrderItem(List<OrderItem> orderItems) {
        // 订单总分销金额
        double totalDistributionAmount = 0.0;
        if (CollectionUtil.isNotEmpty(orderItems)) {
            for (OrderItem orderItem : orderItems) {
                if (StrUtil.isBlank(orderItem.getDistributionCardNo())) {
                    continue;
                }
                // 如果改订单项已经退款了的话，分销员的佣金就已经回退了，不需要继续算钱
                if (Objects.equals(orderItem.getReturnMoneySts(), ReturnMoneyStsType.SUCCESS.value())) {
                    continue;
                }
                // 分销佣金
                if (orderItem.getDistributionAmount() != null && orderItem.getDistributionAmount() > 0) {
                    totalDistributionAmount = Arith.add(totalDistributionAmount, orderItem.getDistributionAmount());
                }
                // 上级分销佣金
                if (orderItem.getDistributionParentAmount() != null && orderItem.getDistributionParentAmount() > 0) {
                    totalDistributionAmount = Arith.add(totalDistributionAmount, orderItem.getDistributionParentAmount());
                }
            }
        }
        return totalDistributionAmount;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeAmount(Order order) {
        Order orderDb = orderMapper.selectOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getOrderId, order.getOrderId())
                .eq(Order::getOrderNumber, order.getOrderNumber())
        );
        if (!Objects.equals(orderDb.getStatus(), OrderStatus.UNPAY.value())) {
            // 订单状态异常，无法更改订单金额
            throw new YamiShopBindException("yami.order.unrecognized.update");
        }
        Integer changeAmountVersion = 0;
        if (Objects.nonNull(orderDb.getChangeAmountVersion())) {
            changeAmountVersion = orderDb.getChangeAmountVersion() + 1;
        }
        //减少金额
        double amount = 0.00;
        //平台优惠金额
        double platformAmount = 0.00;
        Map<Long, OrderItem> collect = order.getOrderItems().stream().collect(Collectors.toMap(OrderItem::getOrderItemId, orderItem -> orderItem));
        List<OrderItem> orderItemList = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderNumber, order.getOrderNumber()));
        for (OrderItem orderItemDb : orderItemList) {
            if (Objects.nonNull(orderItemDb.getGiveawayOrderItemId())) {
                continue;
            }
            OrderItem orderItem = collect.get(orderItemDb.getOrderItemId());
            if (Objects.isNull(orderItem) || Objects.isNull(orderItem.getChageAmount())) {
                continue;
            }

            if (orderItem.getActualTotal() < 0.01 && orderItem.getUseScore() > 0) {
                // 如果金额小于0.01 支付积分大于0则为纯积分支付 此时不进行金额判断
                continue;
            }
            if (orderItem.getChageAmount() >= orderItemDb.getActualTotal() || orderItem.getChageAmount() < 0) {
                // 订单金额必须大于0，或者数据发生变化(请刷新后重试)
                throw new YamiShopBindException("yami.order.amount.check");
            }
            if (Objects.isNull(orderItem.getChageAmount()) || Objects.equals(orderItem.getChageAmount(), 0.00)) {
                continue;
            }
            //修改平台优惠金额
            double playformItemAmount = 0.00;
            if (orderItemDb.getPlatformShareReduce() > 0) {
                //金额减少比例 = 减少金额  % 总金额
                double proportion = Arith.div(orderItem.getChageAmount(), orderItemDb.getProductTotalAmount(), 6);
                //平台优惠金额减少金额 = 减少比例 * 原平台优惠金额
                playformItemAmount = Arith.roundByBanker(Arith.mul(proportion, orderItemDb.getPlatformShareReduce()), 2);
                //平台优惠金额 = 原平台优惠金额 - 对应比例的金额
                orderItemDb.setPlatformShareReduce(Arith.sub(orderItemDb.getPlatformShareReduce(), playformItemAmount));
            }
            // 店铺改价平台优惠减少金额
            orderItemDb.setPlatformShopChangeAmount(playformItemAmount);
            //实际金额 = 原实际金额 - 变化金额
            orderItemDb.setActualTotal(Arith.sub(orderItemDb.getActualTotal(), orderItem.getChageAmount()));
            //总优惠金额 = 变化金额 + 原总优惠金额
            orderItemDb.setShareReduce(Arith.add(orderItem.getChageAmount(), orderItemDb.getShareReduce()));
            // 店铺改价金额为订单项减少的金额
            orderItemDb.setShopChangeFreeAmount(Arith.add(orderItemDb.getShopChangeFreeAmount(), orderItem.getChageAmount()));
            orderItemDb.setChangeAmountVersion(changeAmountVersion);

            amount = Arith.add(amount, orderItem.getChageAmount());
            platformAmount = Arith.add(platformAmount, playformItemAmount);
        }
        // 重新计算佣金
        calculatePlatformCommission(Collections.singletonList(orderDb), orderItemList);
        orderItemService.updateBatchById(orderItemList);
        OrderSettlement orderSettlement = orderSettlementService.getOne(new LambdaQueryWrapper<OrderSettlement>().eq(OrderSettlement::getOrderNumber, order.getOrderNumber()));
        //修改订单信息
        orderDb.setActualTotal(Arith.sub(orderDb.getActualTotal(), amount));
        orderDb.setReduceAmount(Arith.add(orderDb.getReduceAmount(), amount));
        orderDb.setPlatformAmount(Arith.sub(orderDb.getPlatformAmount(), platformAmount));
        orderDb.setShopChangeFreeAmount(orderDb.getShopChangeFreeAmount() + amount);
        // 计算运费变化金额
        if (!Objects.equals(Arith.sub(orderDb.getFreightAmount(),orderDb.getPlatformFreeFreightAmount()) , order.getFreightAmount())) {
            if (order.getFreightAmount() < 0) {
                throw new YamiShopBindException("运费金额不能小于0");
            }
            // 根据订单查看是否自营店
            // 判断会员等级是否绑定包邮权益
            if (Objects.equals(orderDb.getShopId(), Constant.MAIN_SHOP)) {
                eventPublisher.publishEvent(new CheckIsMainShopEvent(orderDb));
            }
            double changeFreightAmount = Arith.sub(order.getFreightAmount(), orderDb.getFreightAmount());
            //修改运费信息
            orderDb.setFreightAmount(order.getFreightAmount());
            orderDb.setFreeTransfee(orderDb.getFreeTransfee() + changeFreightAmount);
            orderDb.setActualTotal(Arith.add(orderDb.getActualTotal(), changeFreightAmount));
        }
        orderDb.setChangeAmountVersion(changeAmountVersion);
        orderMapper.updateById(orderDb);
        orderSettlement.setPayAmount(orderDb.getActualTotal());
        orderSettlementService.updateById(orderSettlement);
        // 失效对应的二维码
        invalidCode(Collections.singletonList(orderDb));
    }

    @Override
    public List<Order> getOrderPayInfoByOrderNumber(List<String> orderNumberList) {
        return orderMapper.getOrderPayInfoByOrderNumber(orderNumberList);
    }

    @Override
    public Order getOrderDetailByOrderNumberAndShopId(String orderNumber, Long shopId, Integer lang) {
        Order order = orderMapper.getOrderDetailByOrderNumberAndShopId(orderNumber, shopId, lang);
        if (Objects.isNull(order) || CollUtil.isEmpty(order.getOrderItems())){
            return order;
        }
        List<OrderRefund> orderRefundList = orderRefundMapper.getProcessingOrderRefundByOrderId(order.getOrderId());
        if (CollUtil.isEmpty(orderRefundList)){
            return order;
        }

        order.setRefundType(orderRefundList.get(0).getRefundType());

        // 整单退款
        if (Objects.equals(order.getRefundType(), RefundType.ALL.value())) {
            OrderRefund orderRefund = orderRefundList.get(0);
            for (OrderItem orderItem : order.getOrderItems()) {
                orderItem.setRefundId(orderRefund.getRefundId());
                orderItem.setReturnMoneySts(orderRefund.getReturnMoneySts());
            }
            return order;
        }
        // 单项退款
        Map<Long, OrderRefund> refundMap = orderRefundList.stream().collect(Collectors.toMap(OrderRefund::getOrderItemId, o -> o));
        for (OrderItem orderItem : order.getOrderItems()) {
            OrderRefund orderRefund = refundMap.get(orderItem.getOrderItemId());
            if (Objects.nonNull(orderRefund)) {
                orderItem.setReturnMoneySts(orderRefund.getReturnMoneySts());
                orderItem.setRefundId(orderRefund.getRefundId());
            }
        }
        return order;
    }

    @Override
    public Map<Long, Integer> getOrderItemMap(Long orderId) {
        List<OrderRefund> orderRefunds = orderRefundMapper.selectList(new LambdaQueryWrapper<OrderRefund>()
                .eq(OrderRefund::getOrderId, orderId)
                .lt(OrderRefund::getReturnMoneySts, 6)
                .gt(OrderRefund::getReturnMoneySts, 0)
        );
        Map<Long, Integer> map = Maps.newHashMap();

        for (OrderRefund orderRefund : orderRefunds) {
            if (orderRefund.getRefundType() == 1) {
                map.put(0L, orderRefund.getReturnMoneySts());
                return map;
            }
            map.put(orderRefund.getOrderItemId(), orderRefund.getReturnMoneySts());
        }
        return map;
    }

    @Override
    public Integer countByOrderNumber(String orderNumber) {
        return orderMapper.countByOrderNumber(orderNumber);
    }

    @Override
    public UnDeliveryOrderExcelVO getOrderAndOrderItemsByOrderNumberAndShopId(String orderNumber, Long shopId) {
        return orderMapper.getOrderAndOrderItemsByOrderNumberAndShopId(orderNumber, shopId);
    }

    @Override
    public List<Order> getOrdersStatus(List<String> orderNumbers) {
        List<Order> orderList = list(new LambdaQueryWrapper<Order>()
                .select(Order::getOrderNumber,Order::getStatus,Order::getOrderType,Order::getActualTotal,Order::getUserId,Order::getCreateTime).in(Order::getOrderNumber,orderNumbers));
        for (String orderNumber : orderNumbers) {
            boolean hasOrderNumber = false;
            for (Order orderStatusBO : orderList) {
                if (StrUtil.equals(orderStatusBO.getOrderNumber(), orderNumber)) {
                    hasOrderNumber = true;
                    break;
                }
            }
            if (!hasOrderNumber) {
                Order orderStatusBO = new Order();
                orderStatusBO.setOrderNumber(orderNumber);
                orderList.add(orderStatusBO);
            }
        }
        return orderList;
    }

    @Override
    public OrderAmountVO getOrdersAmountAndIfNoCancel(List<String> orderNumbers, Integer payType) {
        List<Order> ordersStatus = getOrdersStatus(orderNumbers);
        if (CollUtil.isEmpty(ordersStatus)) {
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }

        for (Order order : ordersStatus) {
            if (!Objects.equals(order.getStatus(), OrderStatus.UNPAY.value())) {
                // 支付失败，订单不在未支付状态
                throw new YamiShopBindException("yami.order.pay.fail");
            }
            if (Objects.isNull(order.getStatus()) || Objects.equals(order.getStatus(), OrderStatus.CLOSE.value())) {
                // 订单已关闭
                throw new YamiShopBindException("yami.order.is.closed");
            }
            // 普通订单创建时间经过限定订单超时分钟，如果为true则早于当前时间表示过期，抛出异常
            boolean isExpired = !DateUtil.offsetMinute(order.getCreateTime(), Constant.ORDER_MAX_TIME).after(new Date());
            if(isExpired){
                // 秒杀订单已经过期，无法进行支付
                throw new YamiShopBindException("yami.order.expired");
            }
            // 如果是秒杀订单,还需判断秒杀订单有没有过期
            if(Objects.equals(order.getOrderType(),OrderType.SECKILL.value())){
                applicationContext.publishEvent(new CheckSecKillOrderEvent(order));
            }
            // 如果是团购订单,还需判断团购订单有没有过期
            if(Objects.equals(order.getOrderType(),OrderType.GROUP.value())){
                applicationContext.publishEvent(new CheckGroupOrderEvent(order));
            }
            order.setPayType(payType);
            update(order, Wrappers.lambdaUpdate(Order.class).eq(Order::getOrderNumber, order.getOrderNumber()));
        }
        return orderMapper.getOrdersActualAmount(orderNumbers);
    }

    @Override
    public void updateByToPaySuccess(List<String> orderNumbers, Integer payType) {
        orderMapper.updateByToPaySuccess(orderNumbers, payType);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void payGoods(PayGoodsParam param,Long shopId) {
        Order order = orderMapper.getOrderByOrderNumber(param.getOrderNumber());
        log.info("用户进行支付货款，订单信息order：{}",order);
        if(order==null || order.getIsPayGoods()){
            throw new YamiShopBindException("yami.shop.order.has.paid");
        }
        ShopWallet shopWallet = shopWalletService.getShopWalletByShopId(shopId);
        BigDecimal bigDecimal = order.getGoodsFee();
        if(bigDecimal==null){
            throw new YamiShopBindException("yami.shop.order.no.goods.free");
        }
        if(shopWallet.getAccountAmount()<=0.0){
            shopWallet.setAccountAmount(0.0);
        }
        BigDecimal accountAmount = new BigDecimal(shopWallet.getAccountAmount());
        if(accountAmount.compareTo(bigDecimal)==-1){
            throw new YamiShopBindException("yami.shop.account.amount.insufficient");
        }
        int result = shopWalletMapper.updateAccountAmount(shopId, 2, bigDecimal);
        if(result<=0){
            throw new YamiShopBindException("yami.shop.account.amount.insufficient");
        }
        order.setIsPayGoods(true);
        this.updateById(order);
        //插入流水
        //增加流水
        ShopWalletLog shopWalletLog = new ShopWalletLog();
        shopWalletLog.setWalletLogId(shopWallet.getShopWalletId());
        shopWalletLog.setShopId(shopId);
        shopWalletLog.setOrderNumber(String.valueOf(param.getOrderNumber()));
        shopWalletLog.setIoType(0);
        shopWalletLog.setAmountType(4);
        shopWalletLog.setChangeAomunt(bigDecimal.doubleValue());
        shopWalletLog.setReason(8);
        shopWalletLog.setCreateTime(new Date());
        shopWalletLogService.save(shopWalletLog);
    }

    @Override
    public Order getOrderAndOrderItemByOrderNumber(String orderNumber) {
        return orderMapper.getOrderAndOrderItemByOrderNumber(orderNumber);
    }

    @Override
    public void getOrderItemRefundStatus(Order order) {
        if (Objects.nonNull(order.getRefundStatus()) && !Objects.equals(order.getRefundStatus(), RefundStatusEnum.DISAGREE.value())) {
            List<OrderRefund> processingOrderRefundByOrderId = orderRefundMapper.getProcessingOrderRefundByOrderId(order.getOrderId());
            for (OrderRefund orderRefund : processingOrderRefundByOrderId) {
                //整单退款
                if (orderRefund.getRefundType() == 1) {
                    for (OrderItem orderItem : order.getOrderItems()) {
                        orderItem.setReturnMoneySts(orderRefund.getReturnMoneySts());
                    }
                    break;
                }
                // 单项退款，每个单号都不一样
                for (OrderItem orderItem : order.getOrderItems()) {
                    if (Objects.equals(orderItem.getOrderItemId(), orderRefund.getOrderItemId())) {
                        orderItem.setReturnMoneySts(orderRefund.getReturnMoneySts());
                    }
                }
            }
        }
    }


    @Override
    public IPage<Order> pageByUserId(PageParam<Order> page, String userId) {
        return orderMapper.getPageByUserId(page, userId);
    }

    @Override
    public List<Order> listPendingSettlementOrders(Integer orderStatus, Date startTime) {
        return orderMapper.listPendingSettlementOrders(orderStatus, startTime);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void orderCommissionSettlement(List<Order> orders) {
        // 众所周知，结算之后是不能改变状态的
        int updateStats = orderMapper.settledOrder(orders);
        if (updateStats == 0) {
            return;
        }
        eventPublisher.publishEvent(new OrderSettlementEvent(orders));
    }


    @Override
    public IPage<MyOrderDto> orderListByStatus(PageParam<MyOrderDto> page, Integer status, Long stationId) {
        List<MyOrderDto> myOrderDtos = orderMapper.orderListByStatusAndStationId(new PageAdapter(page), status, stationId);
        for (MyOrderDto myOrderDto : myOrderDtos) {
            for (MyOrderItemDto orderItemDto : myOrderDto.getOrderItemDtos()) {
                if (Objects.equals(myOrderDto.getOrderMold(), 1)) {
                    orderItemDto.setProdCount(myOrderDto.getProductNums());
                }
            }
        }
        page.setRecords(myOrderDtos);
        List<MyOrderDto> orderDtoList = page.getRecords();
        for (MyOrderDto myOrderDto : orderDtoList) {
            if (StrUtil.isBlank(myOrderDto.getShopName())) {
                myOrderDto.setShopName(Constant.PLATFORM_SHOP_NAME);
            }
        }
        page.setTotal(orderMapper.countByStatusAndStationId(status, stationId));
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean orderStationByOrderNumber(List<String> orderNumberList, String userId, Long stationId) {
        if (CollUtil.isEmpty(orderNumberList)) {
            // 请选择最少一个需要自提的订单
            throw new YamiShopBindException("yami.order.need.station");
        }
        List<Order> orderList = orderMapper.getStationOrderByOrderNumbers(orderNumberList, userId, null);
        Order orderParam = new Order();
        if (CollectionUtils.isEmpty(orderList)) {
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }
        for (Order order : orderList) {
            if (Objects.isNull(order)) {
                // 订单不存在
                throw new YamiShopBindException("yami.order.no.exist");
            }
            orderParam = order;
            if (Objects.equals(order.getOrderMold(), 1)) {
                orderVirtualInfoService.orderWriteOffByOrderNumber(null, order, stationId);
                continue;
            }
            // 如果不是自提订单且不是核销订单就直接报错
            if (!Objects.equals(order.getDvyType(), DvyType.STATION.value()) || !Objects.equals(order.getDvyId(), stationId)) {
                // 订单不存在
                throw new YamiShopBindException("yami.order.no.exist");
            }
            boolean isRefund = Objects.equals(order.getRefundStatus(), RefundStatusEnum.APPLY.value())
                    || Objects.equals(order.getRefundStatus(), RefundStatusEnum.SUCCEED.value());
            if (Objects.nonNull(order.getRefundStatus()) && isRefund) {
                // 订单退款中，无法自提
                throw new YamiShopBindException(I18nMessage.getMessage("yami.order") + order.getOrderNumber() + I18nMessage.getMessage("yami.order.station.check"));
            }
            if (!Objects.equals(order.getStatus(), OrderStatus.PADYED.value())) {
                // 订单已提货
                throw new YamiShopBindException(I18nMessage.getMessage("yami.order") + order.getOrderNumber() + I18nMessage.getMessage("yami.order.station.finish"));
            }
            order.setStatus(OrderStatus.CONSIGNMENT.value());
            order.setDvyTime(new Date());
        }
        if (Objects.isNull(stationId)) {
            stationId = orderParam.getDvyId();
        }
        Station station = stationService.getById(stationId);
//        if (!Objects.equals(station.getStatus(), StationStatusEnum.OPEN.value())) {
//            // 该自提点未在营业状态
//            throw new YamiShopBindException("yami.shop.station.not.open");
//        }
        String stationName = "";
        if (Objects.nonNull(station)) {
            stationName = station.getStationName();
        }

        updateBatchById(orderList);
        // 消息推送-自提点核销通知
        if (orderList.size() > 1) {
            orderParam.setOrderNumber(orderParam.getOrderNumber() + "......");
        }
        notifyTemplateService.writeOffOrder(stationName, orderParam);
        return true;
    }

}
